package com.ecommerce.user.controller;

import com.ecommerce.common.dto.Result;
import com.ecommerce.common.dto.PageResult;
import com.ecommerce.user.dto.UserRegisterRequest;
import com.ecommerce.user.dto.UserLoginRequest;
import com.ecommerce.user.dto.UserLoginResponse;
import com.ecommerce.user.dto.UserResponse;
import com.ecommerce.user.dto.UpdateProfileRequest;
import com.ecommerce.user.dto.ChangePasswordRequest;
import com.ecommerce.user.service.UserService;
import com.ecommerce.user.repository.UserRepository;
import com.ecommerce.common.exception.BusinessException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import jakarta.servlet.http.HttpServletRequest;

/**
 * 用户控制器
 */
@Slf4j
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
@Tag(name = "用户管理", description = "用户注册、登录、信息查询等接口")
public class UserController {

    private final UserService userService;
    private final UserRepository userRepository;

    /**
     * 用户注册
     * @param registerRequest 注册请求
     * @return 用户信息
     */
    @PostMapping("/register")
    @Operation(summary = "用户注册", description = "新用户注册接口")
    public Result<UserResponse> register(@RequestBody UserRegisterRequest registerRequest) {
        log.info("收到用户注册请求: {}", registerRequest.getUsername());
        UserResponse userResponse = userService.register(registerRequest);
        return Result.success("注册成功", userResponse);
    }

    /**
     * 用户登录
     * @param loginRequest 登录请求
     * @return 登录响应
     */
    @PostMapping("/login")
    @Operation(summary = "用户登录", description = "用户登录接口，返回JWT令牌")
    public Result<UserLoginResponse> login(@RequestBody UserLoginRequest loginRequest) {
        log.info("收到用户登录请求: {}", loginRequest.getUsername());
        UserLoginResponse loginResponse = userService.login(loginRequest);
        return Result.success("登录成功", loginResponse);
    }

    /**
     * 根据ID获取用户信息
     * @param userId 用户ID
     * @return 用户信息
     */
    @GetMapping("/{userId}")
    @Operation(summary = "获取用户信息", description = "根据用户ID获取用户详细信息")
    public Result<UserResponse> getUserById(@PathVariable Long userId) {
        log.info("获取用户信息请求，用户ID: {}", userId);
        UserResponse userResponse = userService.getUserById(userId);
        return Result.success(userResponse);
    }

    /**
     * 获取用户详细信息（个人中心）- 从请求头获取用户ID
     * @return 用户详细信息
     */
    @GetMapping("/profile")
    @Operation(summary = "获取当前用户详细信息", description = "从请求头获取用户ID，返回当前用户的详细信息")
    public Result<UserResponse> getCurrentUserProfile() {
        // 从请求头获取用户ID
        String xUserId = getRequest().getHeader("X-User-ID");
        if (xUserId == null || xUserId.isEmpty()) {
            log.warn("获取用户详细信息失败: 请求头中缺少X-User-ID");
            return Result.error("无法获取用户信息");
        }
        
        try {
            Long userId = Long.parseLong(xUserId);
            log.info("获取当前用户详细信息请求，用户ID: {}", userId);
            
            // 检查用户是否存在，如果不存在则尝试从认证服务同步
            if (!userRepository.existsById(userId)) {
                log.warn("用户不存在，尝试从认证服务同步用户数据，用户ID: {}", userId);
                try {
                    // 尝试从认证服务获取用户信息并同步
                    userService.syncUserFromAuthService(userId);
                    log.info("用户数据同步成功，用户ID: {}", userId);
                } catch (Exception syncException) {
                    log.error("从认证服务同步用户数据失败: userId={}, error={}", userId, syncException.getMessage(), syncException);
                    return Result.error("用户不存在且同步失败");
                }
            }
            
            UserResponse userResponse = userService.getUserById(userId);
            return Result.success(userResponse);
        } catch (NumberFormatException e) {
            log.error("解析请求头用户ID失败: {}", xUserId, e);
            return Result.error("无效的用户ID");
        } catch (BusinessException e) {
            log.error("获取用户详细信息失败: userId={}, error={}", xUserId, e.getMessage());
            return Result.error(e.getMessage());
        } catch (Exception e) {
            log.error("获取用户详细信息时发生未知错误: userId={}, error={}", xUserId, e.getMessage(), e);
            return Result.error("获取用户信息失败");
        }
    }

    /**
     * 获取用户详细信息（个人中心）
     * @param userId 用户ID
     * @return 用户详细信息
     */
    @GetMapping("/profile/{userId}")
    @Operation(summary = "获取用户详细信息", description = "获取个人中心所需的用户详细信息")
    public Result<UserResponse> getUserProfile(@PathVariable Long userId) {
        log.info("获取用户详细信息请求，用户ID: {}", userId);
        
        UserResponse userResponse = userService.getUserById(userId);
        return Result.success(userResponse);
    }

    /**
     * 更新用户基本信息
     * @param userId 用户ID
     * @param updateRequest 更新请求
     * @return 更新后的用户信息
     */
    @PutMapping("/profile/{userId}")
    @Operation(summary = "更新用户基本信息", description = "更新用户邮箱、手机号、昵称等基本信息")
    public Result<UserResponse> updateProfile(@PathVariable Long userId, @RequestBody UpdateProfileRequest updateRequest) {
        log.info("更新用户信息请求，用户ID: {}", userId);
        
        // 权限验证：检查请求头中的用户ID是否与路径中的用户ID一致
        String xUserId = getRequest().getHeader("X-User-ID");
        if (xUserId != null && !xUserId.isEmpty()) {
            try {
                Long headerUserId = Long.parseLong(xUserId);
                if (!headerUserId.equals(userId)) {
                    log.warn("权限验证失败: 请求头用户ID {} 与路径用户ID {} 不一致", headerUserId, userId);
                    return Result.error("无权更新其他用户信息");
                }
            } catch (NumberFormatException e) {
                log.error("解析请求头用户ID失败: {}", xUserId, e);
                return Result.error("无效的用户ID");
            }
        }
        
        UserResponse userResponse = userService.updateProfile(userId, updateRequest);
        return Result.success("用户信息更新成功", userResponse);
    }

    /**
     * 修改用户密码
     * @param userId 用户ID
     * @param changePasswordRequest 密码修改请求
     * @return 修改结果
     */
    @PutMapping("/password/{userId}")
    @Operation(summary = "修改用户密码", description = "修改用户登录密码")
    public Result<Boolean> changePassword(@PathVariable Long userId, @RequestBody ChangePasswordRequest changePasswordRequest) {
        log.info("修改用户密码请求，用户ID: {}", userId);
        
        // 获取当前认证用户的ID
        var authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated()) {
            return Result.error("未认证，无法修改密码");
        }
        
        // 权限验证：检查请求头中的用户ID是否与路径中的用户ID一致
        String xUserId = getRequest().getHeader("X-User-ID");
        if (xUserId != null && !xUserId.isEmpty()) {
            try {
                Long headerUserId = Long.parseLong(xUserId);
                if (!headerUserId.equals(userId)) {
                    log.warn("权限验证失败: 请求头用户ID {} 与路径用户ID {} 不一致", headerUserId, userId);
                    return Result.error("无权修改其他用户密码");
                }
            } catch (NumberFormatException e) {
                log.error("解析请求头用户ID失败: {}", xUserId, e);
                return Result.error("无效的用户ID");
            }
        } else {
            // 如果没有X-User-ID请求头，尝试从认证对象中获取用户ID
            String currentUserIdStr = authentication.getPrincipal().toString();
            try {
                Long currentUserId = Long.valueOf(currentUserIdStr);
                
                // 检查是否有权限修改该用户的密码
                if (!currentUserId.equals(userId)) {
                    return Result.error("无权修改其他用户密码");
                }
            } catch (NumberFormatException e) {
                return Result.error("无效的用户ID");
            }
        }
        
        // 调用服务修改密码
        boolean result = userService.changePassword(userId, changePasswordRequest);
        return Result.success("密码修改成功", result);
    }
    
    /**
     * 获取当前请求对象
     * @return HttpServletRequest
     */
    private HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
    }

    /**
     * 更新用户头像
     * @param userId 用户ID
     * @param avatarUrl 头像URL
     * @return 更新后的用户信息
     */
    @PostMapping("/avatar/{userId}")
    @Operation(summary = "更新用户头像", description = "更新用户头像URL")
    public Result<UserResponse> updateAvatar(@PathVariable Long userId, @RequestBody String avatarUrl) {
        log.info("更新用户头像请求，用户ID: {}", userId);
        
        // 权限验证：检查请求头中的用户ID是否与路径中的用户ID一致
        String xUserId = getRequest().getHeader("X-User-ID");
        if (xUserId != null && !xUserId.isEmpty()) {
            try {
                Long headerUserId = Long.parseLong(xUserId);
                if (!headerUserId.equals(userId)) {
                    log.warn("权限验证失败: 请求头用户ID {} 与路径用户ID {} 不一致", headerUserId, userId);
                    return Result.error("无权更新其他用户头像");
                }
            } catch (NumberFormatException e) {
                log.error("解析请求头用户ID失败: {}", xUserId, e);
                return Result.error("无效的用户ID");
            }
        }
        
        UserResponse userResponse = userService.updateAvatar(userId, avatarUrl);
        return Result.success("头像更新成功", userResponse);
    }

    /**
     * 同步用户数据（供认证服务调用）
     * @param syncRequest 同步请求
     * @return 同步结果
     */
    @PostMapping("/sync")
    @Operation(summary = "同步用户数据", description = "从认证服务同步用户数据到用户服务")
    public Result<String> syncUser(@RequestBody SyncUserRequest syncRequest) {
        log.info("收到用户数据同步请求，用户ID: {}", syncRequest.getUserId());
        try {
            userService.syncUser(syncRequest);
            return Result.success("用户数据同步成功");
        } catch (Exception e) {
            log.error("用户数据同步失败: {}", e.getMessage(), e);
            return Result.error("用户数据同步失败: " + e.getMessage());
        }
    }

    /**
     * 同步用户密码
     * @param userId 用户ID
     * @param syncPasswordRequest 密码同步请求
     * @return 同步结果
     */
    @PostMapping("/sync-password/{userId}")
    @Operation(summary = "同步用户密码", description = "从认证服务同步用户密码到用户服务")
    public Result<String> syncPassword(@PathVariable Long userId, @RequestBody SyncPasswordRequest syncPasswordRequest) {
        log.info("收到用户密码同步请求，用户ID: {}", userId);
        try {
            userService.syncPassword(userId, syncPasswordRequest.getEncodedPassword());
            return Result.success("用户密码同步成功");
        } catch (Exception e) {
            log.error("用户密码同步失败: {}", e.getMessage(), e);
            return Result.error("用户密码同步失败: " + e.getMessage());
        }
    }

    /**
     * 获取用户列表（公开接口）
     * @param page 页码
     * @param pageSize 每页大小
     * @param keyword 搜索关键词
     * @param userType 用户类型
     * @param status 用户状态
     * @return 用户列表
     */
    @GetMapping("/list")
    @Operation(summary = "获取用户列表", description = "公开接口，获取用户列表，支持分页和筛选")
    public Result<PageResult<UserResponse>> getUserList(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(required = false) String keyword,
            @RequestParam(required = false) String userType,
            @RequestParam(required = false) Boolean status) {
        
        log.info("获取用户列表请求，页码: {}, 每页大小: {}, 关键词: {}, 用户类型: {}, 状态: {}", 
                page, pageSize, keyword, userType, status);
        
        // 创建分页对象，页码从0开始
        Pageable pageable = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Direction.DESC, "createdAt"));
        
        Page<UserResponse> userPage = userService.getUsers(keyword, userType, status, pageable);
        
        PageResult<UserResponse> pageResult = new PageResult<>();
        pageResult.setList(userPage.getContent());
        pageResult.setTotal(userPage.getTotalElements());
        pageResult.setPage(page);
        pageResult.setPageSize(pageSize);
        pageResult.setTotalPages(userPage.getTotalPages());
        
        return Result.success(pageResult);
    }

    /**
     * 用户同步请求DTO
     */
    public static class SyncUserRequest {
        private Long userId;
        private String username;
        private String email;
        private String phoneNumber;
        private String address;
        private String nickName;
        private String userType;

        public SyncUserRequest() {}

        public SyncUserRequest(Long userId, String username, String email, String phoneNumber, String address, String nickName) {
            this.userId = userId;
            this.username = username;
            this.email = email;
            this.phoneNumber = phoneNumber;
            this.address = address;
            this.nickName = nickName;
        }

        public Long getUserId() {
            return userId;
        }

        public void setUserId(Long userId) {
            this.userId = userId;
        }

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String email) {
            this.email = email;
        }

        public String getPhoneNumber() {
            return phoneNumber;
        }

        public void setPhoneNumber(String phoneNumber) {
            this.phoneNumber = phoneNumber;
        }

        public String getNickName() {
            return nickName;
        }

        public void setNickName(String nickName) {
            this.nickName = nickName;
        }

        public String getAddress() {
            return address;
        }

        public void setAddress(String address) {
            this.address = address;
        }

        public String getUserType() {
            return userType;
        }

        public void setUserType(String userType) {
            this.userType = userType;
        }
    }

    /**
     * 密码同步请求DTO
     */
    public static class SyncPasswordRequest {
        private String encodedPassword;

        public SyncPasswordRequest() {}

        public SyncPasswordRequest(String encodedPassword) {
            this.encodedPassword = encodedPassword;
        }

        public String getEncodedPassword() {
            return encodedPassword;
        }

        public void setEncodedPassword(String encodedPassword) {
            this.encodedPassword = encodedPassword;
        }
    }
}